//demo实际没有什么具体电路或功能，大家注释语法即可，能看懂每句verilog是啥意思就可，不需要纠结整体，testbench_demo.v同理
module demo (
	//时钟信号
    input           clk,
	//复位信号
    input           rst_n,
	//两个位宽为4的输入信号
    input   [3:0]   i_data,
    input   [3:0]   q_data,
	//
    input           ready_in,
	//片选信号
    input   [1:0]   sel,
	//位宽为5的输出信号
    output  [4:0]   out_data,
    output          ready_out     
);

	//两个输入信号和一个输出信号各自对应的一个寄存器
    reg [3:0] i_data_reg;
    reg [3:0] q_data_reg;
    reg [3:0] out_data_reg;

	//用类计数的信号
    reg [3:0] cnt;

    //计数器
	//这个信号从0变到8再归零,循环往复。每当时钟信号传来时,这个信号的值增加1.
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            cnt<=4'b0;
        
        else if(cnt==4'd8)
            cnt<=4'b0;
        
        else 
            cnt<=cnt+1'b1;
    end

    //reg in
	//将i_data和q_data传入的值放进对应的寄存器中
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            i_data_reg<=4'd0;
        else if(cnt==4'd4)
            i_data_reg<=4'd3;
        else if(ready_in)
            i_data_reg<=i_data;
    end
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            q_data_reg<=4'd0;
        else if(cnt==4'd4)
            q_data_reg<=4'd3;
        else if(ready_in)
            q_data_reg<=q_data;
    end  

//-------------------------------------写法1------------------------------------------//
/*
	//这部分的写法是时序逻辑,每当sel信号为00,01,10,11四个不同的值时,就分别将输出寄存器的值设为四种运算的结果
    //MUX
    always @(*) begin
        case (sel)
            2'b00:  out_data_reg = i_data_reg;
            2'b01:  out_data_reg = i_data_reg * q_data_reg;
            2'b10:  out_data_reg = i_data_reg & q_data_reg;
            2'b11:  out_data_reg = i_data_reg && q_data_reg;
            default:;
        endcase
    end

    assign out_data = out_data_reg;
    assign ready_out = ready_in;
*/

//-------------------------------------写法2------------------------------------------//

    //MUX
	//上面的功能的组合逻辑的写法。
    assign out_data = (sel==2'b00) ?  i_data_reg : 
                      (sel==2'b01) ? (i_data_reg * q_data_reg) :
                      (sel==2'b10) ? (i_data_reg & q_data_reg) :
                                     (i_data_reg && q_data_reg);
	
	//ready_out和ready_in的值始终相同
    assign ready_out = ready_in;

endmodule